Align with latest version of WebRTC spec (#20832) * Remove test for getDefaultIceServers which is no longer in the WebRTC spec * Remove unneeded dependency on getUserMedia for testing WebRTC stats * Fix bug in reading stats on receiver The test was trying to read the stats on the receiver using the track from the sender rather than the receiver * Remove obsolete RTCMediaStreamStats tests * Align with latest set of mandatory to implement stats From https://w3c.github.io/webrtc-pc/webrtc.html#mandatory-to-implement-stats * Remove test for obsolete 'stream' stats * Remove RTCRtpParameters features removed from the spec * Align with removal of encodings as receiverparameters Also, use getTransceivers() rather than getReceivers() since stopped receivers aren't provided in getReceivers() * encodings is only for SenderParameters now * Align with specs on content of rtpencoding parameters * Remove abandonned datachannel priority attribute * Align with removal of rtcoauthcredential * Remove test for obsoleted RTCMediaStreamStats * Align with latest MTI stats hiearchy based on https://w3c.github.io/webrtc-pc/webrtc.html#mandatory-to-implement-stats
diff --git a/webrtc/RTCConfiguration-iceServers.html b/webrtc/RTCConfiguration-iceServers.html index 2ef99bf..1cbf1d6 100644 --- a/webrtc/RTCConfiguration-iceServers.html +++ b/webrtc/RTCConfiguration-iceServers.html 
@@ -29,21 +29,14 @@    4.2.2. RTCIceCredentialType Enum  enum RTCIceCredentialType { - "password", - "oauth" - }; - - 4.2.3. RTCOAuthCredential Dictionary - dictionary RTCOAuthCredential { - required DOMString macKey; - required DOMString accessToken; + "password"  };    4.2.4. RTCIceServer Dictionary  dictionary RTCIceServer {  required (DOMString or sequence<DOMString>) urls;  DOMString username; - (DOMString or RTCOAuthCredential) credential; + DOMString credential;  RTCIceCredentialType credentialType = "password";  };  */ @@ -375,7 +368,7 @@  accessToken: ''  }  }] })); - }, 'with turns server, credentialType password, and RTCOauthCredential credential should throw InvalidAccessError'); + }, 'with turns server, credentialType password, and object credential should throw InvalidAccessError');    /*  4.3.2. To set a configuration @@ -393,102 +386,6 @@  }] }));  }, 'with turns server, credentialType oauth, and string credential should throw InvalidAccessError');   - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: 'turns:turn.example.org', - credentialType: 'oauth', - username: 'user', - credential: { - macKey: 'mac', - accessToken: 'token' - } - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - - const server = iceServers[0]; - assert_array_equals(server.urls, ['turns:turn.example.org']); - assert_equals(server.credentialType, 'oauth'); - assert_equals(server.username, 'user'); - - const { credential } = server; - assert_equals(credential.macKey, 'mac'); - assert_equals(credential.accessToken, 'token'); - - }, `with turns server, credentialType oauth and RTCOAuthCredential credential should succeed`); - - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: ['turns:turn.example.org', 'stun:stun1.example.net'], - credentialType: 'oauth', - username: 'user', - credential: { - macKey: 'mac', - accessToken: 'token' - } - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - - const server = iceServers[0]; - assert_array_equals(server.urls, ['turns:turn.example.org', 'stun:stun1.example.net']); - assert_equals(server.credentialType, 'oauth'); - assert_equals(server.username, 'user'); - - const { credential } = server; - assert_equals(credential.macKey, 'mac'); - assert_equals(credential.accessToken, 'token'); - - }, `with both turns and stun server, credentialType oauth and RTCOAuthCredential credential should succeed`); - - // credential type validation is ignored when scheme name is stun - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: 'stun:stun1.example.net', - credentialType: 'oauth', - username: 'user', - credential: 'cred' - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - const server = iceServers[0]; - - assert_array_equals(server.urls, ['stun:stun1.example.net']); - assert_equals(server.credentialType, 'oauth'); - assert_equals(server.username, 'user'); - assert_equals(server.credential, 'cred'); - - }, 'with stun server, credentialType oauth, and string credential should succeed'); - - // credential type validation is ignored when scheme name is stun - config_test(makePc => { - const pc = makePc({ iceServers: [{ - urls: 'stun:stun1.example.net', - credentialType: 'password', - username: 'user', - credential: { - macKey: '', - accessToken: '' - } - }] }); - - const { iceServers } = pc.getConfiguration(); - assert_equals(iceServers.length, 1); - - const server = iceServers[0]; - assert_array_equals(server.urls, ['stun:stun1.example.net']); - assert_equals(server.credentialType, 'password'); - assert_equals(server.username, 'user'); - - const { credential } = server; - assert_equals(credential.macKey, ''); - assert_equals(credential.accessToken, ''); - - }, 'with stun server, credentialType password, and RTCOAuthCredential credential should succeed'); -  /*  Tested  4.3.2. To set a configuration 
diff --git a/webrtc/RTCPeerConnection-getDefaultIceServers.html b/webrtc/RTCPeerConnection-getDefaultIceServers.html deleted file mode 100644 index 4fdbdb8..0000000 --- a/webrtc/RTCPeerConnection-getDefaultIceServers.html +++ /dev/null 
@@ -1,98 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>RTCPeerConnection.getDefaultIceServers</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> - 'use strict'; - - // Test is based on the following editor draft: - // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html - - /* - [Constructor(optional RTCConfiguration configuration)] - interface RTCPeerConnection : EventTarget { - static sequence<RTCIceServer> getDefaultIceServers(); - ... - }; - - dictionary RTCIceServer { - required (DOMString or sequence<DOMString>) urls; - DOMString username; - (DOMString or RTCOAuthCredential) credential; - RTCIceCredentialType credentialType = "password"; - }; - - dictionary RTCOAuthCredential { - required DOMString macKey; - required DOMString accessToken; - }; - - enum RTCIceCredentialType { - "password", - "oauth" - }; - */ - - test(() => { - const iceServers = RTCPeerConnection.getDefaultIceServers(); - - assert_true(Array.isArray(iceServers), - 'Expect iceServers to be an array'); - - // dictionary IDL cannot be tested automatically using idlharness - for(const server of iceServers) { - const { urls, username, credential, credentialType } = server; - - if(Array.isArray(urls)) { - for(const url of urls) { - assert_equals(typeof url, 'string', - 'Expect elements in urls array to be string'); - } - } else { - assert_equals(typeof urls, 'string', - 'Expect urls to be either string or array'); - } - - if(username !== undefined) { - assert_equals(typeof username, 'string', - 'Expect username to be either undefined or string'); - } - - assert_true(credentialType === 'password' || credentialType === 'oauth', - 'Expect credentialType to be either password or oauth') - - if(credential) { - if(typeof(credential) === 'object') { - const { macKey, accessToken } = credential; - assert_equals(typeof macKey, 'string', - 'Expect macKey to be string'); - - assert_equals(typeof accessToken, 'string', - 'Expect accessToken to be string'); - - } else { - assert_equals(typeof credential, 'string', - 'Expect credential to be either undefined, string, or RTCOauthCredential dictionary'); - } - } - } - - // Expect default ice servers to be accepted as valid configuration - const pc = new RTCPeerConnection({ iceServers }); - - // Only make sure there are same number of ice servers configured - // and not do any deep equality checking - assert_equals(pc.getConfiguration().iceServers.length, iceServers.length); - - }, 'RTCPeerConnection.getDefaultIceServers() should return array of RTCIceServer'); - - /* - Coverage Report - Since there is no steps involved and we are only checking basic call, - This is counted as 1 trivial test coverage. - - Tested 1 - Total 1 - */ -</script> 
diff --git a/webrtc/RTCPeerConnection-getStats.https.html b/webrtc/RTCPeerConnection-getStats.https.html index f39fd2c..ede0ab1 100644 --- a/webrtc/RTCPeerConnection-getStats.https.html +++ b/webrtc/RTCPeerConnection-getStats.https.html 
@@ -82,7 +82,7 @@  const pc = new RTCPeerConnection();  t.add_cleanup(() => pc.close());   - const stream = await navigator.mediaDevices.getUserMedia({audio: true}); + const stream = await getNoiseStream({audio: true});  t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));  const [track] = stream.getTracks();  pc.addTransceiver(track); @@ -292,9 +292,6 @@  'Expect video track stats to be found');    assert_equals(videoTrackStats.kind, 'video'); - - assert_true(mediaStreamStats.trackIds.include(audioTrackStats.id)); - assert_true(mediaStreamStats.trackIds.include(videoTrackStats.id));  }    const onConnected = t.step_func(() => { 
diff --git a/webrtc/RTCPeerConnection-mandatory-getStats.https.html b/webrtc/RTCPeerConnection-mandatory-getStats.https.html index 50158d4..7da14cd 100644 --- a/webrtc/RTCPeerConnection-mandatory-getStats.https.html +++ b/webrtc/RTCPeerConnection-mandatory-getStats.https.html 
@@ -24,12 +24,17 @@  "packetsLost",  "jitter",  "packetsDiscarded", + "framesDropped"  ],  RTCInboundRtpStreamStats: [ - "trackId",  "receiverId",  "remoteId",  "framesDecoded", + "nackCount", + "framesReceived", + "bytesReceived", + "totalAudioEnergy", + "totalSamplesDuration"  ],  RTCRemoteInboundRtpStreamStats: [  "localId", @@ -40,10 +45,11 @@  "bytesSent"  ],  RTCOutboundRtpStreamStats: [ - "trackId",  "senderId",  "remoteId",  "framesEncoded", + "nackCount", + "framesSent"  ],  RTCRemoteOutboundRtpStreamStats: [  "localId", @@ -54,6 +60,7 @@  "dataChannelsClosed",  ],  RTCDataChannelStats: [ + "label",  "protocol",  "dataChannelIdentifier",  "state", @@ -62,35 +69,34 @@  "messagesReceived",  "bytesReceived",  ], - RTCMediaStreamStats: [ - "streamIdentifer", - "trackIds", + RTCMediaSourceStats: [ + "trackIdentifier", + "kind" + ], + RTCAudioSourceStats: [ + "totalAudioEnergy", + "totalSamplesDuration" + ], + RTCVideoSourceStats: [ + "width", + "height", + "framesPerSecond"  ],  RTCMediaHandlerStats: [  "trackIdentifier", - "remoteSource", - "ended",  ],  RTCAudioHandlerStats: [ - "audioLevel",  ],  RTCVideoHandlerStats: [ - "frameWidth", - "frameHeight", - "framesPerSecond",  ],  RTCVideoSenderStats: [ - "framesSent",  ],  RTCVideoReceiverStats: [ - "framesReceived", - "framesDecoded", - "framesDropped", - "partialFramesLost",  ],  RTCCodecStats: [  "payloadType",  "codecType", + "mimeType",  "clockRate",  "channels",  "sdpFmtpLine", @@ -98,7 +104,6 @@  RTCTransportStats: [  "bytesSent",  "bytesReceived", - "rtcpTransportStatsId",  "selectedCandidatePairId",  "localCertificateId",  "remoteCertificateId", @@ -108,12 +113,11 @@  "localCandidateId",  "remoteCandidateId",  "state", - "priority",  "nominated",  "bytesSent",  "bytesReceived",  "totalRoundTripTime", - "currentRoundTripTime", + "currentRoundTripTime"  ],  RTCIceCandidateStats: [  "address", @@ -141,7 +145,10 @@  "csrc": "RTCRtpContributingSourceStats",  "peer-connection": "RTCPeerConnectionStats",  "data-channel": "RTCDataChannelStats", - "stream": "RTCMediaStreamStats", + "media-source": { + audio: "RTCAudioSourceStats", + video: "RTCVideoSourceStats" + },  "track": {  video: "RTCSenderVideoTrackAttachmentStats",  audio: "RTCSenderAudioTrackAttachmentStats" @@ -166,10 +173,12 @@  const parents = {  RTCVideoHandlerStats: "RTCMediaHandlerStats",  RTCVideoSenderStats: "RTCVideoHandlerStats", + RTCVideoSourceStats: "RTCMediaSourceStats",  RTCSenderVideoTrackAttachmentStats: "RTCVideoSenderStats",  RTCVideoReceiverStats: "RTCVideoHandlerStats",  RTCAudioHandlerStats: "RTCMediaHandlerStats",  RTCAudioSenderStats: "RTCAudioHandlerStats", + RTCAudioSourceStats: "RTCMediaSourceStats",  RTCSenderAudioTrackAttachmentStats: "RTCAudioSenderStats",  RTCAudioReceiverStats: "RTCAudioHandlerStats",  RTCReceivedRtpStreamStats: "RTCRtpStreamStats", 
diff --git a/webrtc/RTCPeerConnection-ondatachannel.html b/webrtc/RTCPeerConnection-ondatachannel.html index 46fe8e0..0343655 100644 --- a/webrtc/RTCPeerConnection-ondatachannel.html +++ b/webrtc/RTCPeerConnection-ondatachannel.html 
@@ -255,7 +255,7 @@  const dc1 = pc1.createDataChannel('test', {  ordered: false,  maxRetransmits: 1, - protocol: 'custom', + protocol: 'custom'  });    assert_equals(dc1.label, 'test'); 
diff --git a/webrtc/RTCPeerConnection-track-stats.https.html b/webrtc/RTCPeerConnection-track-stats.https.html index 42054ad..7c34422 100644 --- a/webrtc/RTCPeerConnection-track-stats.https.html +++ b/webrtc/RTCPeerConnection-track-stats.https.html 
@@ -48,29 +48,7 @@  async_test(t => {  const pc = new RTCPeerConnection();  t.add_cleanup(() => pc.close()); - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - let track = tracks[0]; - stream = streams[0]; - pc.addTrack(track, stream); - return pc.getStats(); - })) - .then(t.step_func(report => { - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(streamStats != null, 'Has stats for stream'); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'addTrack() without setLocalDescription() yields media stream stats');   - async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close());  let track;  getUserMediaTracksAndStreams(1)  .then(t.step_func(([tracks, streams]) => { @@ -97,107 +75,6 @@  }, 'addTrack() with setLocalDescription() yields track stats');    async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - let track = tracks[0]; - stream = streams[0]; - pc.addTrack(track, stream); - return pc.createOffer(); - })) - .then(t.step_func(offer => { - return pc.setLocalDescription(offer); - })) - .then(t.step_func(() => { - return pc.getStats(); - })) - .then(t.step_func(report => { - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(streamStats != null, 'Has stats for stream'); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'addTrack() with setLocalDescription() yields media stream stats'); - - async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - let track; - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - track = tracks[0]; - stream = streams[0]; - pc.addTrack(track, stream); - return pc.createOffer(); - })) - .then(t.step_func(offer => { - return pc.setLocalDescription(offer); - })) - .then(t.step_func(() => { - return pc.getStats(); - })) - .then(t.step_func(report => { - let trackStats = findStatsByTypeAndId(report, 'track', track.id); - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(trackStats != null && streamStats != null, - 'Has stats for track and stream'); - assert_array_equals(streamStats.trackIds, [ trackStats.id ], - 'streamStats.trackIds == [ trackStats.id ]'); - validateRtcStats(report, trackStats); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'addTrack(): Media stream stats references track stats'); - - async_test(t => { - const pc = new RTCPeerConnection(); - t.add_cleanup(() => pc.close()); - let track; - let stream; - getUserMediaTracksAndStreams(1) - .then(t.step_func(([tracks, streams]) => { - t.add_cleanup(() => tracks.forEach(track => track.stop())); - track = tracks[0]; - stream = streams[0]; - stream.addTrack(track); - for (const track of stream.getTracks()) - pc.addTrack(track, stream); - return pc.createOffer(); - })) - .then(t.step_func(offer => { - return pc.setLocalDescription(offer); - })) - .then(t.step_func(() => { - return pc.getStats(); - })) - .then(t.step_func(report => { - let trackStats = findStatsByTypeAndId(report, 'track', track.id); - let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); - assert_true(trackStats != null && streamStats != null, - 'Has stats for track and stream'); - assert_array_equals(streamStats.trackIds, [ trackStats.id ], - 'streamStats.trackIds == [ trackStats.id ]'); - validateRtcStats(report, trackStats); - validateRtcStats(report, streamStats); - t.done(); - })) - .catch(t.step_func(reason => { - assert_unreached(reason); - })); - }, 'Media stream stats references track stats'); - - async_test(t => {  const caller = new RTCPeerConnection();  t.add_cleanup(() => caller.close());  const callee = new RTCPeerConnection(); 
diff --git a/webrtc/RTCRtpParameters-encodings.html b/webrtc/RTCRtpParameters-encodings.html index 539b269..e1a6e62 100644 --- a/webrtc/RTCRtpParameters-encodings.html +++ b/webrtc/RTCRtpParameters-encodings.html 
@@ -120,7 +120,6 @@  sendEncodings: [{  active: false,  maxBitrate: 8, - maxFramerate: 25,  rid: 'foo'  }]  }); 
diff --git a/webrtc/RTCRtpParameters-helper.js b/webrtc/RTCRtpParameters-helper.js index 17ecfba..d7653c3 100644 --- a/webrtc/RTCRtpParameters-helper.js +++ b/webrtc/RTCRtpParameters-helper.js 
@@ -50,6 +50,11 @@  function validateSenderRtpParameters(param) {  validateRtpParameters(param);   + assert_array_field(param, 'encodings'); + for(const encoding of param.encodings) { + validateEncodingParameters(encoding); + } +  assert_not_equals(param.transactionId, undefined,  'Expect sender param.transactionId to be set');   @@ -101,20 +106,10 @@  sequence<RTCRtpCodecParameters> codecs;  };   - enum RTCDegradationPreference { - "maintain-framerate", - "maintain-resolution", - "balanced" - };  */  function validateRtpParameters(param) {  assert_optional_string_field(param, 'transactionId');   - assert_array_field(param, 'encodings'); - for(const encoding of param.encodings) { - validateEncodingParameters(encoding); - } -  assert_array_field(param, 'headerExtensions');  for(const headerExt of param.headerExtensions) {  validateHeaderExtensionParameters(headerExt); @@ -131,13 +126,8 @@    /*  dictionary RTCRtpEncodingParameters { - RTCDtxStatus dtx;  boolean active; - RTCPriorityType priority; - RTCPriorityType networkPriority; - unsigned long ptime;  unsigned long maxBitrate; - double maxFramerate;    [readonly]  DOMString rid; @@ -145,31 +135,10 @@  double scaleResolutionDownBy;  };   - enum RTCDtxStatus { - "disabled", - "enabled" - }; - - enum RTCPriorityType { - "very-low", - "low", - "medium", - "high" - };  */  function validateEncodingParameters(encoding) { - assert_optional_enum_field(encoding, 'dtx', - ['disabled', 'enabled']); -  assert_optional_boolean_field(encoding, 'active'); - assert_optional_enum_field(encoding, 'priority', - ['very-low', 'low', 'medium', 'high']); - assert_optional_enum_field(encoding, 'networkPriority', - ['very-low', 'low', 'medium', 'high']); - - assert_optional_unsigned_int_field(encoding, 'ptime');  assert_optional_unsigned_int_field(encoding, 'maxBitrate'); - assert_optional_number_field(encoding, 'maxFramerate');    assert_optional_string_field(encoding, 'rid');  assert_optional_number_field(encoding, 'scaleResolutionDownBy'); 
diff --git a/webrtc/RTCRtpReceiver-getParameters.html b/webrtc/RTCRtpReceiver-getParameters.html index 4be0e3b..7047ce7 100644 --- a/webrtc/RTCRtpReceiver-getParameters.html +++ b/webrtc/RTCRtpReceiver-getParameters.html 
@@ -36,12 +36,11 @@  t.add_cleanup(() => pc.close());  pc.addTransceiver('audio');  const callee = await doOfferAnswerExchange(t, pc); - const param = callee.getReceivers()[0].getParameters(); + const param = callee.getTransceivers()[0].receiver.getParameters();  validateReceiverRtpParameters(param);    assert_greater_than(param.headerExtensions.length, 0);  assert_greater_than(param.codecs.length, 0); - assert_equals(param.encodings.length, 1);  }, 'getParameters() with audio receiver');    promise_test(async t => { @@ -49,12 +48,11 @@  t.add_cleanup(() => pc.close());  pc.addTransceiver('video');  const callee = await doOfferAnswerExchange(t, pc); - const param = callee.getReceivers()[0].getParameters(); + const param = callee.getTransceivers()[0].receiver.getParameters();  validateReceiverRtpParameters(param);    assert_greater_than(param.headerExtensions.length, 0);  assert_greater_than(param.codecs.length, 0); - assert_equals(param.encodings.length, 1);  }, 'getParameters() with video receiver');    promise_test(async t => { @@ -67,15 +65,9 @@  ]  });  const callee = await doOfferAnswerExchange(t, pc); - const param = callee.getReceivers()[0].getParameters(); + const param = callee.getTransceivers()[0].receiver.getParameters();  validateReceiverRtpParameters(param); -  assert_greater_than(param.headerExtensions.length, 0);  assert_greater_than(param.codecs.length, 0); - assert_equals(param.encodings.length, 2, 'layer count must match'); - assert_equals(param.encodings[0].rid, "rid1", - 'simulcast rids must match'); - assert_equals(param.encodings[1].rid, "rid2", - 'simulcast rids must match');  }, 'getParameters() with simulcast video receiver');  </script>